package com.gzck.gzck_verson2.webSocket;

import com.gzck.gzck_verson2.pojo.CRCType;
import org.springframework.stereotype.Component;

@Component
public class CRC {

    CRCType crc16_MODBUS = new CRCType(16, 0x8005, 0xffff, true, true, 0x0000);

    /**
     * CRC16校验
     * @param buffer
     * @param length
     * @return
     */
    public int crcCheck(byte[] buffer, int length) {
        int i = 0;
        int crc = crc16_MODBUS.init;

        while (length-- > 0) {
            int currentByte;
            if (crc16_MODBUS.refIn) {
                currentByte = reflectedData(buffer[i++], 8);
            } else {
                currentByte = buffer[i++] & 0xFF;
            }

            crc ^= currentByte << 8;

            for (int j = 0; j < 8; j++) {
                if ((crc & 0x8000) != 0) {
                    crc = (crc << 1) ^ crc16_MODBUS.poly;
                } else {
                    crc <<= 1;
                }
            }
        }

        if (crc16_MODBUS.refOut) {
            crc = reflectedData(crc, 16);
        }

        return crc ^ crc16_MODBUS.xorOut;
    }

    private int reflectedData(int data, int mode) {
        data = ((data & 0xffff0000) >>> 16) | ((data & 0x0000ffff) << 16);
        data = ((data & 0xff00ff00) >>> 8) | ((data & 0x00ff00ff) << 8);
        data = ((data & 0xf0f0f0f0) >>> 4) | ((data & 0x0f0f0f0f) << 4);
        data = ((data & 0xcccccccc) >>> 2) | ((data & 0x33333333) << 2);
        data = ((data & 0xaaaaaaaa) >>> 1) | ((data & 0x55555555) << 1);

        switch (mode) {
            case 32:
                return data;
            case 16:
                return (data >>> 16) & 0xffff;
            case 8:
                return (data >>> 24) & 0xff;
            case 7:
                return (data >>> 25) & 0x7f;
            case 6:
                return (data >>> 26) & 0x3f;
            case 5:
                return (data >>> 27) & 0x1f;
            case 4:
                return (data >>> 28) & 0x0f;
            default:
                return 0;
        }
    }
}
